package com.thssh.ui.lsn04.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.RadialGradient;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.thssh.ui.R;

/**
 * @author zhangyugehu
 * @version V1.0
 * @date 2017/09/13
 * email: zhangyugehu@163.com
 */

public class GradientView extends View {

    private Paint mPaint;
    private Bitmap mBitmap;

    private int[] mColors = new int[]{Color.RED, Color.YELLOW, Color.BLUE, Color.CYAN, Color.GREEN};
    private int mWidth;
    private int mHeight;

    private int mBitmapHeight;
    private int mBitmapWidth;

    private int mTileModeType;

    private boolean useMatrixScale;

    public GradientView(Context context) {
        this(context, null);
    }

    public GradientView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public GradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.img_9);
        mBitmapHeight = mBitmap.getHeight();
        mBitmapWidth = mBitmap.getWidth();

//        useMatrixScale = true;
        mTileModeType = 2;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(mWidth, mHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        drawBitmapShader(canvas);

//        drawLinearGradient(canvas);

        drawRadialGradient(canvas);

//        drawSweepGradient(canvas);

//        drawComposeGradient(canvas);

    }

    /**
     * 组合渲染
     *
     * @param canvas
     */
    private void drawComposeGradient(Canvas canvas) {
        canvas.save();
        BitmapShader bitmapShader = new BitmapShader(mBitmap, getTileMode(), getTileMode());
        int cx = mBitmapWidth / 2;
        int cy = mBitmapHeight / 2;
        RadialGradient radialGradient = new RadialGradient(cx, cy, cx, mColors, null, Shader.TileMode.CLAMP);
        ComposeShader composeShader = new ComposeShader(radialGradient, bitmapShader, PorterDuff.Mode.ADD);
        mPaint.setShader(composeShader);
        canvas.drawRect(0, 0, mBitmapWidth, mBitmapHeight, mPaint);
        canvas.restore();
    }

    /**
     * 渐变/梯度渲染
     *
     * @param canvas
     */
    private void drawSweepGradient(Canvas canvas) {
        canvas.save();
        int cx = mWidth / 2;
        int cy = mHeight / 2;
        SweepGradient sweepGradient = new SweepGradient(cx, cy, mColors, null);
        mPaint.setShader(sweepGradient);
        canvas.drawCircle(cx, cy, cx, mPaint);
        canvas.restore();
    }

    /**
     * 环形渲染
     *
     * @param canvas
     */
    private void drawRadialGradient(Canvas canvas) {
        canvas.save();
        int cx = mWidth / 2;
        int cy = mHeight / 2;
        RadialGradient radialGradient = new RadialGradient(cx, cy, cx, mColors, null, Shader.TileMode.CLAMP);
        mPaint.setShader(radialGradient);
        canvas.drawCircle(cx, cy, cx, mPaint);
        canvas.restore();
    }

    /**
     * 线性渲染
     *
     * @param canvas
     */
    private void drawLinearGradient(Canvas canvas) {
        canvas.save();

        int l = 50;
        int t = 50;
        int r = mWidth - 50;
        int b = mHeight - 50;
        LinearGradient linearGradient = new LinearGradient(l, t, r, b, mColors, null, Shader.TileMode.CLAMP);
        mPaint.setShader(linearGradient);
        canvas.drawRect(l, t, r, b, mPaint);
        canvas.restore();
    }

    /**
     * 位图图像渲染
     *
     * @param canvas
     */
    private void drawBitmapShader(Canvas canvas) {
        canvas.save();

        canvas.drawColor(Color.WHITE);

        Shader.TileMode tileMode = getTileMode();
        BitmapShader shader = new BitmapShader(mBitmap, tileMode, tileMode);
        if(useMatrixScale) {
            Matrix matrix = new Matrix();
            matrix.setScale(0.5f, 0.5f);
            shader.setLocalMatrix(matrix);
        }
        mPaint.setShader(shader);
        RectF rectF = new RectF();
        rectF.set(0, 0, mWidth, mHeight);
//        canvas.drawOval(rectF, mPaint);
//        canvas.drawRect(rectF, mPaint);
        drawByShapeDrawable(shader, canvas);
        canvas.restore();
    }

    private void drawByShapeDrawable(Shader shader, Canvas canvas) {
        canvas.save();
        ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
        shapeDrawable.getPaint().setShader(shader);
        shapeDrawable.setBounds(new Rect(0, 0, mBitmapWidth, mBitmapHeight));
        shapeDrawable.draw(canvas);
        canvas.restore();
    }

    /**
     * TileMode: CLAMP --- 边缘像素拉伸;
     * @return
     */
    private Shader.TileMode getTileMode() {
        switch (mTileModeType){
            case 1:
                return Shader.TileMode.MIRROR;
            case 2:
                return Shader.TileMode.REPEAT;
            case 0:
            default:
                return Shader.TileMode.CLAMP;
        }
    }
}
